/*
 * @(#)WorkflowPermissionTag.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */

package com.dcivision.workflow.taglib;
import java.sql.Connection;
import java.util.Iterator;
import java.util.List;

import javax.servlet.jsp.JspException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemFunctionConstant;
import com.dcivision.framework.Utility;
import com.dcivision.framework.taglib.logic.PermissionTag;
import com.dcivision.user.bean.UserDelegation;
import com.dcivision.user.dao.UserDelegationDAObject;
import com.dcivision.workflow.bean.WorkflowProgress;
import com.dcivision.workflow.bean.WorkflowRecord;
import com.dcivision.workflow.bean.WorkflowStep;
import com.dcivision.workflow.core.WorkflowPermissionManager;
import com.dcivision.workflow.dao.WorkflowStepDAObject;

/**
    WorkflowPermissionTag.java
    @author          dick xie
    @company         DCIVision Limited
    @creation date   09/07/2003
    @version         $Revision: 1.12.2.2 $
*/

public class WorkflowPermissionTag extends PermissionTag {

  public static final String REVISION = "$Revision: 1.12.2.2 $";
  
  private static final Log log = LogFactory.getLog(WorkflowPermissionTag.class);
  
  private WorkflowProgress workflowProgress = null;
  private WorkflowRecord workflowRecord = null;
  private Integer stepID = null;
  private Integer trackID = null;
  private Integer userRecordID = null;
  
  public WorkflowProgress getWorkflowProgress() {
    return workflowProgress;
  }
  
  public void setWorkflowProgress(WorkflowProgress workflowProgress) {
    this.workflowProgress = workflowProgress;
  }
  
  public WorkflowRecord getWorkflowRecord() {
    return workflowRecord;
  }

  public void setWorkflowRecord(WorkflowRecord workflowRecord) {
    this.workflowRecord = workflowRecord;
  }

  /**
   * Constructor
   */
  public WorkflowPermissionTag() {
    super();
  }
  
  public int doStartTag() throws JspException {
    return super.doStartTag();
  }
  
  public int doEndTag() throws JspException {
    return super.doEndTag();
  }
  
  public void release() {
    super.release();
    this.workflowProgress = null;
    this.workflowRecord = null;
    this.stepID = null;
    this.trackID = null;
    this.userRecordID = null;
  }

  /**
   * Method called by the Container to check permission
   */
  public boolean checkPermission() throws ApplicationException {
    SessionContainer sessionCon = (SessionContainer)pageContext.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(sessionCon, (Connection)pageContext.getRequest().getAttribute(GlobalConstant.DB_KEY));
    if (Utility.isEmpty(this.getObjectType())) {
      this.setObjectType(GlobalConstant.WORKFLOW_OWNER_PERMISSION);
    } 
    
    if (Utility.isEmpty(this.getObjectID())) {
      if(!Utility.isEmpty(this.workflowProgress)){
        this.setObjectID(this.workflowProgress.getWorkflowStepID());
      } else if (!Utility.isEmpty(this.stepID)){
        this.setObjectID(this.stepID);
      } else if (!Utility.isEmpty(this.workflowRecord)) {
        this.setObjectID(stepDAO.getSubmitStepByWorkflowRecordID(this.workflowRecord.getID()).getID());
      }
    } 
    String functionCode = (String)pageContext.getRequest().getAttribute(GlobalConstant.FUNCTION_CODE_KEY);
    
    WorkflowPermissionManager wfPermManager = new WorkflowPermissionManager(sessionCon, (Connection)pageContext.getRequest().getAttribute(GlobalConstant.DB_KEY));
    String workflowStepActionType = null;
    if (!Utility.isEmpty(this.workflowProgress)) {
      workflowStepActionType = ((WorkflowStep)stepDAO.getObjectByID(this.workflowProgress.getWorkflowStepID())).getActionType();
    } else if (!Utility.isEmpty(this.stepID)) {
      workflowStepActionType = ((WorkflowStep)stepDAO.getObjectByID(this.stepID)).getActionType();
    } else if (!Utility.isEmpty(this.workflowRecord)) {
      workflowStepActionType = ((WorkflowStep)stepDAO.getSubmitStepByWorkflowRecordID(this.workflowRecord.getID())).getActionType();
    }
     /*
    if (pageContext.getRequest().getAttribute("WF_" + this.getObjectType() + "_" + this.getObjectID() + "_" + this.getRight()) != null) {
      return(((Boolean)pageContext.getRequest().getAttribute("WF_" + this.getObjectType() + "_" + this.getObjectID() + "_" + this.getRight())).booleanValue());
    }
    */
    
    boolean hasRight;
    
    // Ignor permission checked for all of automatic tasks.
    boolean ignorPermissionCheck = SystemFunctionConstant.WORKFLOW_MONITOR.equals(functionCode)
    || SystemFunctionConstant.WORKFLOW_RECORD.equals(functionCode)
    || WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(workflowStepActionType)
    || WorkflowStep.ACTION_TYPE_END.equals(workflowStepActionType)
    || WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(workflowStepActionType);
    
    if (ignorPermissionCheck) {
      hasRight = true;
    } else if (!Utility.isEmpty(this.workflowProgress)) {
      hasRight = wfPermManager.hasAccessRight(this.getObjectType(), this.workflowProgress, this.getRight(), this.userRecordID);
    } else if (!Utility.isEmpty(this.stepID)) {
      hasRight = wfPermManager.hasAccessRight(this.getObjectType(), this.stepID, this.trackID, this.getRight(), this.userRecordID);
    } else if (!Utility.isEmpty(this.workflowRecord)) {
      hasRight = wfPermManager.hasAccessRight(this.getObjectType(), stepDAO.getSubmitStepByWorkflowRecordID(this.workflowRecord.getID()).getID(), this.trackID, this.getRight(), this.userRecordID);
    } else {
     hasRight = false; 
    }
    if(!hasRight)
      hasRight=checkDelegateUserPermission();//check delegateUser Permission
    /*
    pageContext.getRequest().setAttribute("WF_" + this.getObjectType() + "_" + this.getObjectID() + "_" + this.getRight(), new Boolean(hasRight));
    */
    return(hasRight);
  }
  
  private boolean checkDelegateUserPermission(){
    SessionContainer sessionCon = (SessionContainer)pageContext.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);
    Connection conn = (Connection)pageContext.getRequest().getAttribute(GlobalConstant.DB_KEY);
    UserDelegationDAObject delegationDAO = new UserDelegationDAObject(sessionCon,conn);
    WorkflowPermissionManager wfPermManager = new WorkflowPermissionManager(sessionCon,conn);
    try {
      List delegationList = delegationDAO.getListDelegatedToUser();
      for(Iterator it=delegationList.iterator();it.hasNext();){
        UserDelegation userDelegation = (UserDelegation)it.next();
        boolean hasRight = false;
        if (!Utility.isEmpty(this.workflowProgress)) {
          hasRight = wfPermManager.hasAccessRight(this.getObjectType(), this.workflowProgress, this.getRight(),userDelegation.getSourceUserID() );
        } else if (!Utility.isEmpty(this.stepID)) {
          hasRight = wfPermManager.hasAccessRight(this.getObjectType(), this.stepID, this.trackID, this.getRight(), userDelegation.getSourceUserID());
        } else {
          hasRight = false; 
        }
        if(hasRight)
          return hasRight;
      }

    } catch (ApplicationException e) {
      log.error(e, e);
    }
    return false;
  }
  public Integer getStepID() {
    return stepID;
  }
  
  public void setStepID(Integer stepID) {
    this.stepID = stepID;
  }
  
  public Integer getUserRecordID() {
    return userRecordID;
  }
  
  public void setUserRecordID(Integer userRecordID) {
    this.userRecordID = userRecordID;
  }
  
	public Integer getTrackID() {
		return trackID;
	}
  
	public void setTrackID(Integer trackID) {
		this.trackID = trackID;
	}
}